<?php

namespace app\admin\controller\auth;

use app\admin\controller\Base;
use brand\Brand;
use brand\build\Columns;
use brand\logic\BrandHelper;
use brand\page\Form;
use brand\page\Table;
use brand\tools\Tree;
use app\admin\model\AuthRule;
use app\admin\model\AuthGroup;
use app\admin\model\AuthGroupAccess;
use think\Exception;
use think\facade\Db;

/**
 * 角色组.
 *
 * @icon fa fa-group
 * @remark 角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别下级的角色组或管理员
 */
class Group extends Base
{
    protected $model = null;
    //当前登录管理员所有子组别
    protected $childrenGroupIds = [];
    //当前组别列表数据
    protected $groupdata = [];
    //无需要权限判断的方法
    protected $noNeedRight = ['roletree'];
    protected $pk = 'id';

    public $curdName = 'auth_group';

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new AuthGroup();

        $this->childrenGroupIds = $this->auth->getChildrenGroupIds(true);

        $groupList = AuthGroup::where('id', 'in', $this->childrenGroupIds)->select()->toArray();

        Tree::instance()->init($groupList);
        $result = [];
        if ($this->auth->isSuperAdmin()) {
            $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
        } else {
            $groups = $this->auth->getGroups();
            foreach ($groups as $m => $n) {
                $result = array_merge($result,
                    Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid'])));
            }
        }
        $groupName = [];
        foreach ($result as $k => $v) {
            $groupName[$v['id']] = $v['name'];
        }

        $this->groupdata = $groupName;

    }


    public function table_init()
    {
        Table::$visible_edit = '_options';
        Table::$visible_delete = '_options';
        Table::$header_buttons = ['add','delete'];
        Table::$custom_button[] = Brand::Builder()->build_button('分配权限','el-icon-set-up')
            ->button_visible('_options')
            ->button_url(url('assigns')->build())
            ->button_data(['id'])
            ->build();
    }

    public function form_before_build($raw)
    {
        $pid_select =[];

        foreach ($this->groupdata as $key=>$groupdatum) {
            $pid_select[] = ['label' => $groupdatum,'value' => $key];
        }
        Columns::setForm('pid', 'options' ,$pid_select);
        return $raw;
    }


    public function _tableData()
    {
        $list = AuthGroup::select(array_keys($this->groupdata));
        $list = $list->toArray();
        $groupList = [];
        foreach ($list as $k => $v) {
            $groupList[$v['id']] = $v;
        }
        $list = [];
        foreach ($this->groupdata as $k => $v) {
            if (isset($groupList[$k])) {
                $groupList[$k]['name'] = $v;
                $groupList[$k]['_options'] = $groupList[$k]['rules'] != '*';
                $list[] = $groupList[$k];
            }
        }
        $total = count($list);
        return _success('', ['total' => $total, 'list' => $list]);
    }

    public function assigns()
    {
        $id = input('id');
        $model = $this->model->find($id);
        if (!$model) {
            throw new \Exception('角色不存在');
        }

        if ($this->request->isAjax()){

            $params = $this->request->param();
            // 父级别的规则节点
            $parentmodel = $this->model->find($model->pid);
            if (! $parentmodel) {
                return _error(__('The parent group can not found'));
            }
            // 当前组别的规则节点
            $currentrules = $this->auth->getRuleIds();
            $rules = $params['rules']['value'];
            $parentrules = explode(',', $parentmodel->rules);

            // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限
            $rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules);
            // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
            $rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
            $params['rules'] = implode(',', $rules);

            Db::startTrans();
            try {
                $model->save($params);
                Db::commit();
                return _success('操作成功');
            }catch (Exception $e){
                Db::rollback();
                return _error($e->getMessage());
            }


        }


        $defaultCheckedKeys = explode(',',$model->rules);

        $tree = $this->roletree($model->pid,$model->id);


//        Form::$SurfaceForm->columns([
//            (new \surface\form\components\Tree('rules', "权限"))->props(
//                [
//                    'showCheckbox'       => true,
//                    'node-key'           => 'id',
//                    'default-expand-all' => true,
//                    'check-strictly'     => true,
//                    'default-checked-keys' => $defaultCheckedKeys,
//                    'data'               => $tree
//                ]
//            ),
//        ]);

        $props = [
            'checked_ids'   => $defaultCheckedKeys,
            "nodeKey"=>"id"
        ];
        $array_options["rules"] = Form::$SurfaceForm->column('rules','权限')
            ->el('ba_tree')
            ->props($props)
            ->options($tree)
            ->value(['value'=>$defaultCheckedKeys]);

        Form::buildColumns($array_options);

        return Form::buildView();


    }

    /**
     * 读取角色权限树.
     *
     * @internal
     */
    public function roletree($pid = 1, $id = 0)
    {

        $model = new AuthGroup();
        $parentGroupModel = $model->find($pid);
        $currentGroupModel = null;
        if ($id) {
            $currentGroupModel = $model->find($id);
        }
        if (($pid || $parentGroupModel) && (! $id || $currentGroupModel)) {
            $id = $id ? $id : null;
            $ruleList = AuthRule::order('weigh', 'desc')->order('id', 'asc')->select()->toArray();
            //读取父类角色所有节点列表
            $parentRuleList = [];
            if (in_array('*', explode(',', $parentGroupModel->rules))) {
                $parentRuleList = $ruleList;
            } else {
                $parentRuleIds = explode(',', $parentGroupModel->rules);
                foreach ($ruleList as $k => $v) {
                    if (in_array($v['id'], $parentRuleIds)) {
                        $parentRuleList[] = $v;
                    }
                }
            }
            $ruleTree = new Tree();
            $groupTree = new Tree();
            //当前所有正常规则列表
            $ruleTree->init($parentRuleList);
            //角色组列表
            $groupTree->init(AuthGroup::where('id', 'in',$this->childrenGroupIds)->select()->toArray());
            //是否是超级管理员
            $superadmin = $this->auth->isSuperAdmin();
            //读取当前角色下规则ID集合
            $adminRuleIds = $this->auth->getRuleIds();
            //当前拥有的规则ID集合
            $currentRuleIds = $id ? explode(',', $currentGroupModel->rules) : [];
            if (! $id || ! in_array($pid, $this->childrenGroupIds) || ! in_array($pid,$groupTree->getChildrenIds($id, true))) {
                $parentRuleList = $ruleTree->getTreeList($ruleTree->getTreeArray(0), 'name');

                $hasChildrens = [];
                foreach ($parentRuleList as $k => $v) {
                    if ($v['haschild']) {
                        $hasChildrens[] = $v['id'];
                    }
                }
                $parentRuleIds = array_map(function ($item) {
                    return $item['id'];
                }, $parentRuleList);
                $nodeList = [];
                foreach ($parentRuleList as $k => $v) {
                    if (! $superadmin && ! in_array($v['id'], $adminRuleIds)) {
                        continue;
                    }
                    if ($v['pid'] && ! in_array($v['pid'], $parentRuleIds)) {
                        continue;
                    }

                    $nodeList[] = [
                        'id'     => $v['id'],
                        'parent' => $v['pid'] ? $v['pid'] : '#',
                        'label'   =>__($v['title']) ." 【{$v['name']}】" ,
                        'children'   => [],
                    ];
                }
                return $this->format($nodeList);
            } else {
                $this->error(__('Can not change the parent to child'));
            }



        } else {
            $this->error(__('Group not found'));
        }
    }

    private function format(array $lists,$pid=0)
    {
        $data = [];

        foreach ($lists as $k => $v)
        {
            if($pid != $v['parent']) continue;
            $v['children'] = $this->format($lists,$v['id']);
            $data[] = $v;

        }

        return $data;
    }

    public function submit_save_before($params)
    {
        $params['rules'] = "";
        return $params;
    }

}
